package com.umeox.watch.moto.launcher.fragment;


import static com.umeox.watch.moto.launcher.bean.NotificationBean.TYPE_CALL;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.CallLog;
import android.text.TextUtils;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.umeox.moto.common.log.Logger;
import com.umeox.moto.watch.themes.app.ThemeFragment;
import com.umeox.watch.moto.dataservice.DataProvider;
import com.umeox.watch.moto.launcher.BaseApplication;
import com.umeox.watch.moto.launcher.R;
import com.umeox.watch.moto.launcher.adapter.NotificationAdapter;
import com.umeox.watch.moto.launcher.bean.NotificationBean;
import com.umeox.watch.moto.launcher.constant.AppEntry;
import com.umeox.watch.moto.launcher.constant.Constant;
import com.umeox.watch.moto.launcher.event.NotificationManagerEvent;
import com.umeox.watch.moto.launcher.swipedismiss.SimpleItemTouchHelperCallback;
import com.umeox.watch.moto.launcher.utils.MessageUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.Executors;

/**
 * Created by Rambo 2019-07-04
 * Describe:
 */
public class NotificationFragment extends ThemeFragment implements NotificationAdapter.CancelSwipeEvent, NotificationAdapter.OnItemClickListener {

    private static final String ACTION_NEW_CHAT_MSG = "com.wherecom.intent.action.NOTIFY_CHAT_MSG";
    private static final String ACTION_CLEAR_NOTIFY_CHAT = "com.wherecom.intent.action.CLEAR_NOTIFY_CHAT";
    private static final String ACTION_CLEAR_NOTIFY_CALL = "com.wherecom.intent.action.CLEAR_NOTIFY_CALL";
    private static final String ACTION_CLEAR_NOTIFY_CONTACT = "com.wherecom.intent.action.CLEAR_NOTIFY_CONTACT";
    public static final String EXTRA_CONTACT_NUMBER = "extra_contact_number";
    public static final String EXTRA_ACTION_CHAT_ID = "extra_action_chat_id";
    public static final String STATE_DATA = "DATA";


    private static NotificationFragment INSTANCE;
    private NotificationAdapter mNotificationAdapter;
    ItemTouchHelper touchHelper;
    private LinearLayoutManager mLayoutManager;
    private View mEmptyView;
    private boolean mRefuse;
    private NotificationBean mNoticationBeanTemp;
    private boolean mIsVisibleToUser;
    private long mLastTime;
    private Context mContext;

    public NotificationFragment() {
        INSTANCE = this;
    }

    public static NotificationFragment getInstance() {

        if (INSTANCE == null) {
            INSTANCE = new NotificationFragment();
            final Bundle bundle = new Bundle();
            bundle.putBoolean(Constant.KEY_CLEAR_FRAGMENT, true);
            INSTANCE.setArguments(bundle);
        }
        return INSTANCE;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        if (savedInstanceState == null) {
            return;
        }

        final ArrayList<NotificationBean> datas = savedInstanceState.getParcelableArrayList(STATE_DATA);
        if (datas == null) {
            return;
        }
        mNotificationAdapter.getDatas().addAll(datas);
        mNotificationAdapter.notifyDataSetChanged();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        final ArrayList<NotificationBean> datas = (ArrayList<NotificationBean>) mNotificationAdapter.getDatas();
        outState.putParcelableArrayList(STATE_DATA, datas);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.frag_notification;
    }

    @Override
    protected void initView(View rootView) {
        RecyclerView notificationRv = rootView.findViewById(R.id.notification_recycler);
        mEmptyView = rootView.findViewById(R.id.tv_nft_empty);
        notificationRv.setHasFixedSize(true);
        mNotificationAdapter = new NotificationAdapter(mContext, this);
        mNotificationAdapter.setCancelSwipeEventListener(this);
        mLayoutManager = new LinearLayoutManager(mContext);
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        notificationRv.setLayoutManager(mLayoutManager);
        notificationRv.setAdapter(mNotificationAdapter);
        attachItemTouchHelper(notificationRv);
        registerObserver();
    }

    @Override
    public void onResume() {
        super.onResume();
        mIsVisibleToUser = true;
        EventBus.getDefault().post(new NotificationManagerEvent(0));
        mLastTime = SystemClock.elapsedRealtime();

    }

    @Override
    public void onPause() {
        super.onPause();
        mIsVisibleToUser = false;
    }


    private void attachItemTouchHelper(RecyclerView notificationRv) {
        ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mNotificationAdapter);
        touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(notificationRv);
    }

    /**
     * 注册数据库监听
     */
    private void registerObserver() {
        EventBus.getDefault().register(this);
        final ContentResolver contentResolver = BaseApplication.getContext().getContentResolver();
        contentResolver.registerContentObserver(DataProvider.VideoCallProvider.getUri(), true, mVideoCallObserver);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_NEW_CHAT_MSG);
        intentFilter.addAction(ACTION_CLEAR_NOTIFY_CHAT);
        intentFilter.addAction(ACTION_CLEAR_NOTIFY_CONTACT);
        intentFilter.addAction(ACTION_CLEAR_NOTIFY_CALL);
        BaseApplication.getContext().registerReceiver(mNewMsgReceiver, intentFilter);
    }

    /**
     * 取消注册数据库监听
     */
    private void unregisterObserver() {
        EventBus.getDefault().unregister(this);
        final ContentResolver contentResolver = BaseApplication.getContext().getContentResolver();
        contentResolver.unregisterContentObserver(mVideoCallObserver);
    }


    @Override
    public void onSwipeEventCanceled() {
        touchHelper.attachToRecyclerView(null);
    }

    @Override
    public void onItemClick(NotificationBean notificationBean) {
//        final List<NotificationBean> notificationBeans = mNotificationAdapter.getDatas();
//
//        if (position >= notificationBeans.size()) {
//            return;
//        }
//        NotificationBean notificationBean = notificationBeans.get(position);
        int type = notificationBean.getType();
        if (type == TYPE_CALL) {
            ComponentName componentName = new ComponentName(AppEntry.Contacts.PKG, AppEntry.Contacts.CLS);
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            intent.setComponent(componentName);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            startActivity(intent);
        } else if (type == NotificationBean.TYPE_CHAT) {
            mNoticationBeanTemp = notificationBean;
            String uid = notificationBean.getId();
            //rtc://outgoing/video?friendId=luffy.xiao$umeox.com
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("chat://view?uid=" + uid)));
        } else if (type == NotificationBean.TYPE_PTT_CHAT) {
            mNoticationBeanTemp = notificationBean;
            String uid = notificationBean.getId();
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("ptt_chat://view?uid=" + uid)));
        } else {
            mNoticationBeanTemp = notificationBean;
            final String number = notificationBean.getId();
            Uri uri = Uri.parse("tel:" + number);
            Intent intent = new Intent(Intent.ACTION_CALL, uri);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
            ContentValues values = new ContentValues();
            values.put(CallLog.Calls.NEW, 0);
            mContext.getContentResolver().update(CallLog.Calls.CONTENT_URI, values, "type =? AND new=? AND number=?", new String[]{"3", "1", number});
        }

        mEmptyView.postDelayed(this::removeData, 1000);
    }

    private void removeData() {

        EventBus.getDefault().post(new NotificationManagerEvent(0));

        if (mNoticationBeanTemp != null) {
            final List<NotificationBean> datas = mNotificationAdapter.getDatas();
            final int index = datas.indexOf(mNoticationBeanTemp);

            if (index >= 0) {
                datas.remove(index);
                mNotificationAdapter.notifyItemRemoved(index);
                mNoticationBeanTemp = null;
                mNotificationAdapter.notifyDataSetChanged();
            }
        }
    }

    @Subscribe
    public void onNotificationBeanEvent(NotificationBean notificationBean) {
        requireActivity().runOnUiThread(() -> notifyDataChange(notificationBean));
    }

    @Override
    public void onRefreshEmptyView(boolean empty) {
        mEmptyView.setVisibility(empty ? View.VISIBLE : View.GONE);
    }

    @Override
    public void notifyItemRemoved(int position) {
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unregisterObserver();
    }

    /**
     * 未接视频通话记录
     */
    private final ContentObserver mVideoCallObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {

            Executors.newSingleThreadExecutor().execute(() -> {
                final String lastPathSegment = uri.getLastPathSegment();
                final NotificationBean notificationBean = MessageUtil.getMissedVideoCalled(BaseApplication.getContext(), lastPathSegment);
                if (notificationBean == null) {
                    return;
                }
                getActivity().runOnUiThread(() -> notifyDataChange(notificationBean));
            });

        }
    };


    private BroadcastReceiver mNewMsgReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (TextUtils.isEmpty(action)) {
                return;
            }

            if (ACTION_NEW_CHAT_MSG.equals(action) && !mRefuse) {
                NotificationBean notificationBean = new NotificationBean();
                notificationBean.setId(intent.getStringExtra("uid"));
                notificationBean.setTitle(intent.getStringExtra("name"));
                notificationBean.setIcon(intent.getStringExtra("avatar"));
                notificationBean.setTime(intent.getLongExtra("timestamp", System.currentTimeMillis()));
                int msgType = intent.getIntExtra("msgType", 1);
                notificationBean.setType(msgType == 31 ? NotificationBean.TYPE_PTT_CHAT : NotificationBean.TYPE_CHAT);
                notificationBean.setGroupMsg(intent.getIntExtra("type",0) == 1);
                notificationBean.setCount(1);
                notifyDataChange(notificationBean);
            } else if (ACTION_CLEAR_NOTIFY_CHAT.equals(action)) {
                mRefuse = intent.getBooleanExtra(ACTION_CLEAR_NOTIFY_CHAT, false);
                final String friendId = intent.getStringExtra(EXTRA_ACTION_CHAT_ID);
                if (!TextUtils.isEmpty(friendId)) {
                    mNoticationBeanTemp = new NotificationBean();
                    mNoticationBeanTemp.setId(friendId);
                    mNoticationBeanTemp.setType(NotificationBean.TYPE_CHAT);
                    removeData();
                }
            } else if (ACTION_CLEAR_NOTIFY_CONTACT.equals(action)) {
                mEmptyView.postDelayed(() -> clearContactData(intent), 600);
            } else if (ACTION_CLEAR_NOTIFY_CALL.equals(action)) {
                final String address = intent.getStringExtra("address");
                NotificationBean bean = new NotificationBean();
                bean.setId(address);
                bean.setType(TYPE_CALL);
                mNotificationAdapter.getDatas().remove(bean);

            }
        }
    };

    private void clearContactData(Intent intent) {

        EventBus.getDefault().post(new NotificationManagerEvent(0));

        final ArrayList<String> contactNumbers = intent.getStringArrayListExtra(EXTRA_CONTACT_NUMBER);
        if (contactNumbers == null) {
            return;
        }

        List<NotificationBean> mRemoveBeans = new ArrayList<>();
        for (String number : contactNumbers) {
            NotificationBean bean = new NotificationBean();
            bean.setId(number);
            bean.setType(TYPE_CALL);
            mRemoveBeans.add(bean);
        }

        final List<NotificationBean> datas = mNotificationAdapter.getDatas();
        datas.removeAll(mRemoveBeans);
        mNotificationAdapter.notifyDataSetChanged();

    }

    /**
     * 刷新通知界面列表
     *
     * @param bean
     */
    private void notifyDataChange(NotificationBean bean) {

        final List<NotificationBean> notificationBeans = mNotificationAdapter.getDatas();
        final int index = notificationBeans.indexOf(bean);

        if (index >= 0) {
            final NotificationBean notificationBean = notificationBeans.get(index);
            final LinkedHashSet<Long> times = notificationBean.getTimes();
            Logger.d(TAG, "notifyDataChange1: " + times.size() + " " + times);
            times.add(bean.getTime());
            bean.setTimes(times);
            final LinkedHashSet<Long> beanTimes = bean.getTimes();
            Logger.d(TAG, "notifyDataChange2: " + beanTimes.size() + " " + beanTimes);
            if (notificationBean.getTime() == bean.getTime()) {
                return;
            }
            notificationBeans.set(index, bean);
            Collections.swap(notificationBeans, index, 0);
            mNotificationAdapter.notifyItemChanged(index);
            mNotificationAdapter.notifyItemChanged(0);
            mNotificationAdapter.onItemMove(index, 0);
            mLayoutManager.scrollToPosition(0);
        } else {
            bean.getTimes().add(bean.getTime());
            Logger.d(TAG, "notifyDataChange3: " + bean.getTimes());
            notificationBeans.add(0, bean);
            mNotificationAdapter.notifyItemInserted(0);
            mLayoutManager.scrollToPosition(0);
        }
        if (!mIsVisibleToUser) {
            int count = 0;
            for (NotificationBean notificationBean : notificationBeans) {
                final LinkedHashSet<Long> beanTimes = notificationBean.getTimes();
                Logger.d(TAG, "notifyDataChange beanTimes: " + beanTimes.size());
                for (Long time : beanTimes) {
                    Logger.d(TAG, "notifyDataChange time: " + time + " news:" + (time > mLastTime));
                    if (time > mLastTime) {
                        count++;
                    }
                }
            }
            EventBus.getDefault().post(new NotificationManagerEvent(count));
        }
    }
}
